package com.lft13.producterconsumer;

/**
 * Function: 		A {@code TestProducterConsumer} 测试：生产者消费者模型 ——> 信号灯法，利用标志位解决<br/>
 * Reason:   		ADD REASON.<br/>
 * <p>
 * 生产者，消费者，产品，缓冲区
 * <p>
 * Date:            2021-01-28 14:20<br/>
 * <p>
 * Class Name:      TestProducterConsumer<br/>
 * Package Name:    com.lft13.producterconsumer<br/>
 * @author Laifengting / E-mail:laifengting@foxmail.com
 * @version 1.0.0
 * @since JDK 8
 */
public class TestProducterConsumer2 {
	public static void main(String[] args) {
		TV tv = new TV();
		new Player(tv).start();
		new Watcher(tv).start();
	}
}

/**
 * 生产者——演员
 */
class Player extends Thread {
	private TV tv;
	
	public Player(TV tv) {
		this.tv = tv;
	}
	
	@Override
	public void run() {
		for (int i = 1; i <= 20; i++) {
			if (i % 2 == 0) {
				this.tv.play("第 " + i + " 出《淮海战役》");
			} else {
				this.tv.play("第 " + i + " 出《大风车》");
			}
		}
	}
}

/**
 * 消费者——观众
 */
class Watcher extends Thread {
	private TV tv;
	
	public Watcher(TV tv) {
		this.tv = tv;
	}
	
	@Override
	public void run() {
		for (int i = 0; i <= 20; i++) {
			this.tv.watch();
		}
	}
}

/**
 * 产品——节目
 */
class TV {
	// 演员录制节目，观众等待 True
	// 观众观看节目，演员等待 False
	
	/**
	 * 表演的节目
	 */
	String voice;
	/**
	 * 信号灯——标志位,true  表示没有节目，false 表示有节目
	 */
	boolean flag = true;
	
	/**
	 * 表演
	 */
	public synchronized void play(String voice) {
		// 有节目，演员等待。
		if (!flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			// 没有节目，制作节目，通知观众观看。
			System.out.println("演员表演了:" + voice + " 节目");
			
			// 通知观众观看。
			this.notifyAll();
			this.voice = voice;
			this.flag = !this.flag;
		}
	}
	
	/**
	 * 观看
	 */
	public synchronized void watch() {
		// 没有节目，就等待。
		if (flag) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			// 有节目，观看节目，通知演员制作节目。
			System.out.println("观众观看了:" + voice + " 节目");
			
			// 通知演员制作节目
			this.notifyAll();
			this.flag = !this.flag;
		}
	}
}